/*
 * @(#)Bootstrap.java   1.0   May 7, 2007
 *
 * Copyright 2000-2007 ETH Zurich. All Rights Reserved.
 *
 * This software is the proprietary information of ETH Zurich.
 * Use is subject to license terms.
 *
 * @(#) $Id: Bootstrap.java 435 2007-05-23 12:54:49Z D\aldespin $
 */
package ch.ethz.globis.javaom.system;

import ch.ethz.globis.javaom.core.Tuple;

/**
 * @author aldespin
 * @version 1.0
 */
public class Bootstrap {

   public static Metadata bootstrap() {

      Metadata metadata = new Metadata();

      // create objects
      Bootstrap.createTypes(metadata);
      Bootstrap.createAttributes(metadata);
      Bootstrap.createCollections(metadata);
      Bootstrap.createBinaryCollections(metadata);
      Bootstrap.createBulks(metadata);

      // register extent collections
      Bootstrap.registerExtentCollections(metadata);

      // associate types with attributes
      Bootstrap.declareAttributes(metadata);

      // associate objects with their type attribute values
      Bootstrap.dressAsTypes(metadata);

      // associate objects with their attribute attribute values
      Bootstrap.dressAsAttributes(metadata);

      // associate objects with their collection attribute values
      Bootstrap.dressAsCollections(metadata);

      // associate objects with their binarycollection attribute values
      Bootstrap.dressAsBinaryCollections(metadata);

      // create hierarchies
      Bootstrap.createTypeHierarchy(metadata);
      Bootstrap.createCollectionHierarchy(metadata);

      // associate objects with their types
      Bootstrap.dressTypes(metadata);
      Bootstrap.dressAttributes(metadata);
      Bootstrap.dressCollections(metadata);
      Bootstrap.dressBinaryCollections(metadata);
      Bootstrap.dressBulks(metadata);
      Bootstrap.dressStrings(metadata);
      // TODO the tuples created here will not be dressed
      Bootstrap.dressTuples(metadata);

      // populate extent collections
      Bootstrap.populateCollections(metadata);
      Bootstrap.populateAttributes(metadata);
      Bootstrap.populateBinaryCollections(metadata);
      Bootstrap.populateObjects(metadata);
      Bootstrap.populateStrings(metadata);
      Bootstrap.populateTuples(metadata);
      Bootstrap.populateTypes(metadata);
      Bootstrap.populateBulks(metadata);

      return metadata;
   }

   private static void createTypes(final Metadata metadata) {
      // ... create object type
      metadata.createTypeObject(Metadata.OBJECT);
      // ... create type type
      metadata.createTypeObject(Metadata.TYPE);
      // ... create attribute type
      metadata.createTypeObject(Metadata.ATTRIBUTE);
      // ... create collection type
      metadata.createTypeObject(Metadata.COLLECTION);
      // ... create binarycollection type
      metadata.createTypeObject(Metadata.BINARYCOLLECTION);
      // ... create string type
      metadata.createTypeObject(Metadata.STRING);
      // ... create tuple type
      metadata.createTypeObject(Metadata.TUPLE);
      // ... create bulk type
      metadata.createTypeObject(Metadata.BULK);
   }

   private static void createAttributes(final Metadata metadata) {
      // ... create type name attribute
      metadata.createAttributeObject(Metadata.TYPE, Metadata.NAME);

      // ... create attribute name attribute
      metadata.createAttributeObject(Metadata.ATTRIBUTE, Metadata.NAME);
      // ... create attribute type attribute
      metadata.createAttributeObject(Metadata.ATTRIBUTE, Metadata.TYPE);

      // ... create collection name attribute
      metadata.createAttributeObject(Metadata.COLLECTION, Metadata.NAME);
      // ... create collection mebertype attribute
      metadata.createAttributeObject(Metadata.COLLECTION, Metadata.MEMBERTYPE);
      // ... create collection extent attribute
      metadata.createAttributeObject(Metadata.COLLECTION, Metadata.EXTENT);

      // TODO ... create binarycollection name attribute
      // metadata.createAttributeObject(Metadata.BINARYCOLLECTION, Metadata.NAME);
      // ... create collection domain mebertype attribute
      metadata.createAttributeObject(Metadata.BINARYCOLLECTION, Metadata.DOMAIN_MEMBERTYPE);
      // ... create collection range mebertype attribute
      metadata.createAttributeObject(Metadata.BINARYCOLLECTION, Metadata.RANGE_MEMBERTYPE);
      // TODO ... create binarycollection extent attribute
      // metadata.createAttributeObject(Metadata.BINARYCOLLECTION, Metadata.EXTENT);

      // ... create tuple domain attribute
      metadata.createAttributeObject(Metadata.TUPLE, Metadata.DOMAIN_VALUE);
      // ... create tuple range attribute
      metadata.createAttributeObject(Metadata.TUPLE, Metadata.RANGE_VALUE);
   }

   private static void createCollections(final Metadata metadata) {
      metadata.createExtentCollection(Metadata.OBJECT);
      metadata.createExtentCollection(Metadata.TYPE);
      metadata.createExtentCollection(Metadata.ATTRIBUTE);
      metadata.createExtentCollection(Metadata.COLLECTION);
      metadata.createExtentCollection(Metadata.BINARYCOLLECTION);
      metadata.createExtentCollection(Metadata.STRING);
      metadata.createExtentCollection(Metadata.TUPLE);
      metadata.createExtentCollection(Metadata.BULK);
   }

   private static void createBinaryCollections(final Metadata metadata) {
      metadata.createBinaryCollection(Metadata.OBJECT_HAS_TYPES);
      metadata.createBinaryCollection(Metadata.TYPE_HAS_ATTRIBUTES);
      metadata.createBinaryCollection(Metadata.OBJECT_HAS_ATTRIBUTEVALUES);
      metadata.createBinaryCollection(Metadata.ATTRIBUTEVALUES);
      metadata.createBinaryCollection(Metadata.TYPE_HAS_EXTENT);
      metadata.createBinaryCollection(Metadata.TYPE_ISA);
      metadata.createBinaryCollection(Metadata.COLLECTION_ISA);
   }

   private static void createBulks(final Metadata metadata) {
      metadata.createCollectionExtent(Metadata.getExtentCollectionName(Metadata.OBJECT));
      metadata.createCollectionExtent(Metadata.getExtentCollectionName(Metadata.TYPE));
      metadata.createCollectionExtent(Metadata.getExtentCollectionName(Metadata.ATTRIBUTE));
      metadata.createCollectionExtent(Metadata.getExtentCollectionName(Metadata.COLLECTION));
      metadata.createCollectionExtent(Metadata.getExtentCollectionName(Metadata.BINARYCOLLECTION));
      metadata.createCollectionExtent(Metadata.getExtentCollectionName(Metadata.STRING));
      metadata.createCollectionExtent(Metadata.getExtentCollectionName(Metadata.TUPLE));
      metadata.createCollectionExtent(Metadata.getExtentCollectionName(Metadata.BULK));

      metadata.createBinaryCollectionExtent(Metadata.OBJECT_HAS_TYPES);
      metadata.createBinaryCollectionExtent(Metadata.TYPE_HAS_ATTRIBUTES);
      metadata.createBinaryCollectionExtent(Metadata.OBJECT_HAS_ATTRIBUTEVALUES);
      metadata.createBinaryCollectionExtent(Metadata.ATTRIBUTEVALUES);
      metadata.createBinaryCollectionExtent(Metadata.TYPE_HAS_EXTENT);
      metadata.createBinaryCollectionExtent(Metadata.TYPE_ISA);
      metadata.createBinaryCollectionExtent(Metadata.COLLECTION_ISA);
   }

   private static void dressTypes(final Metadata metadata) {
      for (ch.ethz.globis.javaom.core.Object current : metadata.getTypeObjects()) {
         metadata.getBinaryCollectionExtent(Metadata.OBJECT_HAS_TYPES).add(
               metadata.createTuple(Metadata.OBJECT_HAS_TYPES, current, metadata
                     .getTypeObject(Metadata.TYPE)));
      }
   }

   private static void dressAttributes(final Metadata metadata) {
      for (ch.ethz.globis.javaom.core.Object current : metadata.getAttributeObjects()) {
         metadata.getBinaryCollectionExtent(Metadata.OBJECT_HAS_TYPES).add(
               metadata.createTuple(Metadata.OBJECT_HAS_TYPES, current, metadata
                     .getTypeObject(Metadata.ATTRIBUTE)));
      }
   }

   private static void dressCollections(final Metadata metadata) {
      for (ch.ethz.globis.javaom.core.Object current : metadata.getExtentCollections()) {
         metadata.getBinaryCollectionExtent(Metadata.OBJECT_HAS_TYPES).add(
               metadata.createTuple(Metadata.OBJECT_HAS_TYPES, current, metadata
                     .getTypeObject(Metadata.COLLECTION)));
      }
   }

   private static void dressBinaryCollections(final Metadata metadata) {
      for (ch.ethz.globis.javaom.core.Object current : metadata.getBinaryCollections()) {
         metadata.getBinaryCollectionExtent(Metadata.OBJECT_HAS_TYPES).add(
               metadata.createTuple(Metadata.OBJECT_HAS_TYPES, current, metadata
                     .getTypeObject(Metadata.BINARYCOLLECTION)));
      }
   }

   private static void dressStrings(final Metadata metadata) {
      for (ch.ethz.globis.javaom.core.Object current : metadata.getStringValues()) {
         metadata.getBinaryCollectionExtent(Metadata.OBJECT_HAS_TYPES).add(
               metadata.createTuple(Metadata.OBJECT_HAS_TYPES, current, metadata
                     .getTypeObject(Metadata.STRING)));
      }
   }

   private static void dressTuples(final Metadata metadata) {
      for (ch.ethz.globis.javaom.core.Object current : metadata.getTuples()) {
         metadata.getBinaryCollectionExtent(Metadata.OBJECT_HAS_TYPES).add(
               metadata.createTuple(Metadata.OBJECT_HAS_TYPES, current, metadata
                     .getTypeObject(Metadata.TUPLE)));
      }
   }

   private static void dressBulks(final Metadata metadata) {
      for (ch.ethz.globis.javaom.core.Object current : metadata.getExtents()) {
         metadata.getBinaryCollectionExtent(Metadata.OBJECT_HAS_TYPES).add(
               metadata.createTuple(Metadata.OBJECT_HAS_TYPES, current, metadata
                     .getTypeObject(Metadata.BULK)));
      }
   }

   private static void registerExtentCollections(final Metadata metadata) {
      metadata.getBinaryCollectionExtent(Metadata.TYPE_HAS_EXTENT).add(
            metadata.createTuple(Metadata.TYPE_HAS_EXTENT,
                  metadata.getTypeObject(Metadata.OBJECT), metadata
                        .getExtentCollection(Metadata.OBJECT)));

      metadata.getBinaryCollectionExtent(Metadata.TYPE_HAS_EXTENT).add(
            metadata.createTuple(Metadata.TYPE_HAS_EXTENT, metadata.getTypeObject(Metadata.TYPE),
                  metadata.getExtentCollection(Metadata.TYPE)));

      metadata.getBinaryCollectionExtent(Metadata.TYPE_HAS_EXTENT).add(
            metadata.createTuple(Metadata.TYPE_HAS_EXTENT, metadata
                  .getTypeObject(Metadata.ATTRIBUTE), metadata
                  .getExtentCollection(Metadata.ATTRIBUTE)));

      metadata.getBinaryCollectionExtent(Metadata.TYPE_HAS_EXTENT).add(
            metadata.createTuple(Metadata.TYPE_HAS_EXTENT, metadata
                  .getTypeObject(Metadata.COLLECTION), metadata
                  .getExtentCollection(Metadata.COLLECTION)));

      metadata.getBinaryCollectionExtent(Metadata.TYPE_HAS_EXTENT).add(
            metadata.createTuple(Metadata.TYPE_HAS_EXTENT, metadata
                  .getTypeObject(Metadata.BINARYCOLLECTION), metadata
                  .getExtentCollection(Metadata.BINARYCOLLECTION)));

      metadata.getBinaryCollectionExtent(Metadata.TYPE_HAS_EXTENT).add(
            metadata.createTuple(Metadata.TYPE_HAS_EXTENT, metadata.getTypeObject(Metadata.TUPLE),
                  metadata.getExtentCollection(Metadata.TUPLE)));

      metadata.getBinaryCollectionExtent(Metadata.TYPE_HAS_EXTENT).add(
            metadata.createTuple(Metadata.TYPE_HAS_EXTENT,
                  metadata.getTypeObject(Metadata.STRING), metadata
                        .getExtentCollection(Metadata.STRING)));

      metadata.getBinaryCollectionExtent(Metadata.TYPE_HAS_EXTENT).add(
            metadata.createTuple(Metadata.TYPE_HAS_EXTENT, metadata.getTypeObject(Metadata.BULK),
                  metadata.getExtentCollection(Metadata.BULK)));
   }

   private static void declareAttributes(final Metadata metadata) {

      // ... type declares type name attribute
      metadata.getBinaryCollectionExtent(Metadata.TYPE_HAS_ATTRIBUTES).add(
            metadata.createTuple(Metadata.TYPE_HAS_ATTRIBUTES, metadata
                  .getTypeObject(Metadata.TYPE), metadata.getAttributeObject(Metadata.TYPE,
                  Metadata.NAME)));

      // ... attribute declares attribute name attribute
      metadata.getBinaryCollectionExtent(Metadata.TYPE_HAS_ATTRIBUTES).add(
            metadata.createTuple(Metadata.TYPE_HAS_ATTRIBUTES, metadata
                  .getTypeObject(Metadata.ATTRIBUTE), metadata.getAttributeObject(
                  Metadata.ATTRIBUTE, Metadata.NAME)));
      // ... attribute declares attribute type attribute
      metadata.getBinaryCollectionExtent(Metadata.TYPE_HAS_ATTRIBUTES).add(
            metadata.createTuple(Metadata.TYPE_HAS_ATTRIBUTES, metadata
                  .getTypeObject(Metadata.ATTRIBUTE), metadata.getAttributeObject(
                  Metadata.ATTRIBUTE, Metadata.TYPE)));

      // ... collection declares collection name attribute
      metadata.getBinaryCollectionExtent(Metadata.TYPE_HAS_ATTRIBUTES).add(
            metadata.createTuple(Metadata.TYPE_HAS_ATTRIBUTES, metadata
                  .getTypeObject(Metadata.COLLECTION), metadata.getAttributeObject(
                  Metadata.COLLECTION, Metadata.NAME)));
      // ... collection declares collection membertype attribute
      metadata.getBinaryCollectionExtent(Metadata.TYPE_HAS_ATTRIBUTES).add(
            metadata.createTuple(Metadata.TYPE_HAS_ATTRIBUTES, metadata
                  .getTypeObject(Metadata.COLLECTION), metadata.getAttributeObject(
                  Metadata.COLLECTION, Metadata.MEMBERTYPE)));
      // ... collection declares collection extent attribute
      metadata.getBinaryCollectionExtent(Metadata.TYPE_HAS_ATTRIBUTES).add(
            metadata.createTuple(Metadata.TYPE_HAS_ATTRIBUTES, metadata
                  .getTypeObject(Metadata.COLLECTION), metadata.getAttributeObject(
                  Metadata.COLLECTION, Metadata.EXTENT)));

      // TODO ... binarycollection declares binarycollection name attribute
      // metadata.getBinaryCollectionExtent(Metadata.TYPE_HAS_ATTRIBUTES).add(
      // metadata.createTuple(Metadata.TYPE_HAS_ATTRIBUTES, metadata
      // .getTypeObject(Metadata.BINARYCOLLECTION), metadata.getAttributeObject(
      // Metadata.BINARYCOLLECTION, Metadata.NAME)));
      // ... binarycollection declares binarycollection domain membertype attribute
      metadata.getBinaryCollectionExtent(Metadata.TYPE_HAS_ATTRIBUTES).add(
            metadata.createTuple(Metadata.TYPE_HAS_ATTRIBUTES, metadata
                  .getTypeObject(Metadata.BINARYCOLLECTION), metadata.getAttributeObject(
                  Metadata.BINARYCOLLECTION, Metadata.DOMAIN_MEMBERTYPE)));
      // ... binarycollection declares binarycollection range membertype attribute
      metadata.getBinaryCollectionExtent(Metadata.TYPE_HAS_ATTRIBUTES).add(
            metadata.createTuple(Metadata.TYPE_HAS_ATTRIBUTES, metadata
                  .getTypeObject(Metadata.BINARYCOLLECTION), metadata.getAttributeObject(
                  Metadata.BINARYCOLLECTION, Metadata.RANGE_MEMBERTYPE)));
      // TODO ... binarycollection declares binarycollection extent attribute
      // metadata.getBinaryCollectionExtent(Metadata.TYPE_HAS_ATTRIBUTES).add(
      // metadata.createTuple(Metadata.TYPE_HAS_ATTRIBUTES, metadata
      // .getTypeObject(Metadata.BINARYCOLLECTION), metadata.getAttributeObject(
      // Metadata.BINARYCOLLECTION, Metadata.EXTENT)));

      // ... tuple declares domain value attribute
      metadata.getBinaryCollectionExtent(Metadata.TYPE_HAS_ATTRIBUTES).add(
            metadata.createTuple(Metadata.TYPE_HAS_ATTRIBUTES, metadata
                  .getTypeObject(Metadata.TUPLE), metadata.getAttributeObject(Metadata.TUPLE,
                  Metadata.DOMAIN_VALUE)));
      // ... tuple declares range value attribute
      metadata.getBinaryCollectionExtent(Metadata.TYPE_HAS_ATTRIBUTES).add(
            metadata.createTuple(Metadata.TYPE_HAS_ATTRIBUTES, metadata
                  .getTypeObject(Metadata.TUPLE), metadata.getAttributeObject(Metadata.TUPLE,
                  Metadata.RANGE_VALUE)));
   }

   private static void dressAsType(final Metadata metadata,
         final ch.ethz.globis.javaom.core.Object type, final String name) {

      // ... create tuple from type name attribute to name value
      final Tuple tuple =
            metadata.createTuple(Metadata.ATTRIBUTEVALUES, metadata.getAttributeObject(
                  Metadata.TYPE, Metadata.NAME), metadata.createStringValue(name));

      // ... add to association from attribute to value
      metadata.getBinaryCollectionExtent(Metadata.ATTRIBUTEVALUES).add(tuple);

      // ... add to association from type to attributevalues
      metadata.getBinaryCollectionExtent(Metadata.OBJECT_HAS_ATTRIBUTEVALUES).add(
            metadata.createTuple(Metadata.OBJECT_HAS_ATTRIBUTEVALUES, type, tuple));
   }

   private static void dressAsTypes(final Metadata metadata) {

      // ... object has type name attribute = "object"
      Bootstrap.dressAsType(metadata, metadata.getTypeObject(Metadata.OBJECT), Metadata.OBJECT);

      // ... type has type name attribute = "type"
      Bootstrap.dressAsType(metadata, metadata.getTypeObject(Metadata.TYPE), Metadata.TYPE);

      // ... attribute has type name attribute = "attribute"
      Bootstrap.dressAsType(metadata, metadata.getTypeObject(Metadata.ATTRIBUTE),
            Metadata.ATTRIBUTE);

      // ... collection has type name attribute = "collection"
      Bootstrap.dressAsType(metadata, metadata.getTypeObject(Metadata.COLLECTION),
            Metadata.COLLECTION);

      // ... binarycollection has type name attribute = "binarycollection"
      Bootstrap.dressAsType(metadata, metadata.getTypeObject(Metadata.BINARYCOLLECTION),
            Metadata.BINARYCOLLECTION);

      // ... string has type name attribute = "string"
      Bootstrap.dressAsType(metadata, metadata.getTypeObject(Metadata.STRING), Metadata.STRING);

      // ... tuple has type name attribute = "tuple"
      Bootstrap.dressAsType(metadata, metadata.getTypeObject(Metadata.TUPLE), Metadata.TUPLE);

      // ... bulk has type name attribute = "bulk"
      Bootstrap.dressAsType(metadata, metadata.getTypeObject(Metadata.BULK), Metadata.BULK);
   }

   private static void dressAsAttribute(final Metadata metadata,
         final ch.ethz.globis.javaom.core.Object attribute, final String name,
         final ch.ethz.globis.javaom.core.Object type) {

      // ... create tuple from name attribute to name value
      final Tuple nameTuple =
            metadata.createTuple(Metadata.ATTRIBUTEVALUES, metadata.getAttributeObject(
                  Metadata.ATTRIBUTE, Metadata.NAME), metadata.createStringValue(name));
      // ... create tuple from type attribute to type value
      final Tuple typeTuple =
            metadata.createTuple(Metadata.ATTRIBUTEVALUES, metadata.getAttributeObject(
                  Metadata.ATTRIBUTE, Metadata.TYPE), type);

      // ... add to association from name attribute to name value
      metadata.getBinaryCollectionExtent(Metadata.ATTRIBUTEVALUES).add(nameTuple);
      // ... add to association from type attribute to type value
      metadata.getBinaryCollectionExtent(Metadata.ATTRIBUTEVALUES).add(typeTuple);

      // ... add to association from attribute to attributevalues
      metadata.getBinaryCollectionExtent(Metadata.OBJECT_HAS_ATTRIBUTEVALUES).add(
            metadata.createTuple(Metadata.OBJECT_HAS_ATTRIBUTEVALUES, attribute, nameTuple));
      metadata.getBinaryCollectionExtent(Metadata.OBJECT_HAS_ATTRIBUTEVALUES).add(
            metadata.createTuple(Metadata.OBJECT_HAS_ATTRIBUTEVALUES, attribute, typeTuple));
   }

   private static void dressAsAttributes(final Metadata metadata) {

      // type name
      Bootstrap.dressAsAttribute(metadata, metadata.getAttributeObject(Metadata.TYPE,
            Metadata.NAME), Metadata.NAME, metadata.getTypeObject(Metadata.STRING));

      // attribute name
      Bootstrap.dressAsAttribute(metadata, metadata.getAttributeObject(Metadata.ATTRIBUTE,
            Metadata.NAME), Metadata.NAME, metadata.getTypeObject(Metadata.STRING));

      // attribute type
      Bootstrap.dressAsAttribute(metadata, metadata.getAttributeObject(Metadata.ATTRIBUTE,
            Metadata.TYPE), Metadata.TYPE, metadata.getTypeObject(Metadata.TYPE));

      // collection name
      Bootstrap.dressAsAttribute(metadata, metadata.getAttributeObject(Metadata.COLLECTION,
            Metadata.NAME), Metadata.NAME, metadata.getTypeObject(Metadata.STRING));

      // collection membertype
      Bootstrap.dressAsAttribute(metadata, metadata.getAttributeObject(Metadata.COLLECTION,
            Metadata.MEMBERTYPE), Metadata.MEMBERTYPE, metadata.getTypeObject(Metadata.TYPE));

      // collection extent
      Bootstrap.dressAsAttribute(metadata, metadata.getAttributeObject(Metadata.COLLECTION,
            Metadata.EXTENT), Metadata.EXTENT, metadata.getTypeObject(Metadata.BULK));

      // TODO binarycollection name
      // Bootstrap.dressAsAttribute(metadata,
      // metadata.getAttributeObject(Metadata.BINARYCOLLECTION,
      // Metadata.NAME), Metadata.NAME, metadata.getTypeObject(Metadata.STRING));

      // binarycollection domain membertype
      Bootstrap.dressAsAttribute(metadata, metadata.getAttributeObject(Metadata.BINARYCOLLECTION,
            Metadata.DOMAIN_MEMBERTYPE), Metadata.DOMAIN_MEMBERTYPE, metadata
            .getTypeObject(Metadata.TYPE));

      // binarycollection range membertype
      Bootstrap.dressAsAttribute(metadata, metadata.getAttributeObject(Metadata.BINARYCOLLECTION,
            Metadata.RANGE_MEMBERTYPE), Metadata.RANGE_MEMBERTYPE, metadata
            .getTypeObject(Metadata.TYPE));

      // TODO collection extent
      // Bootstrap.dressAsAttribute(metadata,
      // metadata.getAttributeObject(Metadata.BINARYCOLLECTION,
      // Metadata.EXTENT), Metadata.EXTENT, metadata.getTypeObject(Metadata.BULK));

      // tuple domain value
      Bootstrap
            .dressAsAttribute(metadata, metadata.getAttributeObject(Metadata.TUPLE,
                  Metadata.DOMAIN_VALUE), Metadata.DOMAIN_VALUE, metadata
                  .getTypeObject(Metadata.OBJECT));
      // tuple range value
      Bootstrap.dressAsAttribute(metadata, metadata.getAttributeObject(Metadata.TUPLE,
            Metadata.RANGE_VALUE), Metadata.RANGE_VALUE, metadata.getTypeObject(Metadata.OBJECT));
   }

   private static void dressAsCollection(final Metadata metadata,
         final ch.ethz.globis.javaom.core.Object collection, final String name,
         final ch.ethz.globis.javaom.core.Object membertype,
         final ch.ethz.globis.javaom.core.Object extent) {

      // ... create tuple from name attribute to name value
      final Tuple nameTuple =
            metadata.createTuple(Metadata.ATTRIBUTEVALUES, metadata.getAttributeObject(
                  Metadata.COLLECTION, Metadata.NAME), metadata.createStringValue(name));
      // ... create tuple from membertype attribute to membertype value
      final Tuple membertypeTuple =
            metadata.createTuple(Metadata.ATTRIBUTEVALUES, metadata.getAttributeObject(
                  Metadata.COLLECTION, Metadata.MEMBERTYPE), membertype);
      // ... create tuple from extent attribute to extent value
      final Tuple extentTuple =
            metadata.createTuple(Metadata.ATTRIBUTEVALUES, metadata.getAttributeObject(
                  Metadata.COLLECTION, Metadata.EXTENT), extent);

      // ... add to association from name attribute to name value
      metadata.getBinaryCollectionExtent(Metadata.ATTRIBUTEVALUES).add(nameTuple);
      // ... add to association from membertype attribute to membertype value
      metadata.getBinaryCollectionExtent(Metadata.ATTRIBUTEVALUES).add(membertypeTuple);
      // ... add to association from extent attribute to bulk value
      metadata.getBinaryCollectionExtent(Metadata.ATTRIBUTEVALUES).add(extentTuple);

      // ... add to association from objects to attributevalues
      metadata.getBinaryCollectionExtent(Metadata.OBJECT_HAS_ATTRIBUTEVALUES).add(
            metadata.createTuple(Metadata.OBJECT_HAS_ATTRIBUTEVALUES, collection, nameTuple));
      metadata.getBinaryCollectionExtent(Metadata.OBJECT_HAS_ATTRIBUTEVALUES)
            .add(
                  metadata.createTuple(Metadata.OBJECT_HAS_ATTRIBUTEVALUES, collection,
                        membertypeTuple));
      metadata.getBinaryCollectionExtent(Metadata.OBJECT_HAS_ATTRIBUTEVALUES).add(
            metadata.createTuple(Metadata.OBJECT_HAS_ATTRIBUTEVALUES, collection, extentTuple));
   }

   private static void dressAsCollections(final Metadata metadata) {

      // objects
      Bootstrap.dressAsCollection(metadata, metadata.getExtentCollection(Metadata.OBJECT),
            Metadata.getExtentCollectionName(Metadata.OBJECT), metadata
                  .getTypeObject(Metadata.OBJECT), metadata.getCollectionExtent(Metadata.OBJECT));

      // types
      Bootstrap.dressAsCollection(metadata, metadata.getExtentCollection(Metadata.TYPE), Metadata
            .getExtentCollectionName(Metadata.TYPE), metadata.getTypeObject(Metadata.TYPE),
            metadata.getCollectionExtent(Metadata.TYPE));

      // attributes
      Bootstrap.dressAsCollection(metadata, metadata.getExtentCollection(Metadata.ATTRIBUTE),
            Metadata.getExtentCollectionName(Metadata.ATTRIBUTE), metadata
                  .getTypeObject(Metadata.ATTRIBUTE), metadata
                  .getCollectionExtent(Metadata.ATTRIBUTE));

      // collections
      Bootstrap.dressAsCollection(metadata, metadata.getExtentCollection(Metadata.COLLECTION),
            Metadata.getExtentCollectionName(Metadata.COLLECTION), metadata
                  .getTypeObject(Metadata.COLLECTION), metadata
                  .getCollectionExtent(Metadata.COLLECTION));

      // binarycollections
      Bootstrap.dressAsCollection(metadata, metadata
            .getExtentCollection(Metadata.BINARYCOLLECTION), Metadata
            .getExtentCollectionName(Metadata.BINARYCOLLECTION), metadata
            .getTypeObject(Metadata.BINARYCOLLECTION), metadata
            .getCollectionExtent(Metadata.BINARYCOLLECTION));

      // tuples
      Bootstrap.dressAsCollection(metadata, metadata.getExtentCollection(Metadata.TUPLE), Metadata
            .getExtentCollectionName(Metadata.TUPLE), metadata.getTypeObject(Metadata.TUPLE),
            metadata.getCollectionExtent(Metadata.TUPLE));

      // strings
      Bootstrap.dressAsCollection(metadata, metadata.getExtentCollection(Metadata.STRING),
            Metadata.getExtentCollectionName(Metadata.STRING), metadata
                  .getTypeObject(Metadata.STRING), metadata.getCollectionExtent(Metadata.STRING));

      // bulks
      Bootstrap.dressAsCollection(metadata, metadata.getExtentCollection(Metadata.BULK), Metadata
            .getExtentCollectionName(Metadata.BULK), metadata.getTypeObject(Metadata.BULK),
            metadata.getCollectionExtent(Metadata.BULK));

      // objectHasTypes
      Bootstrap.dressAsCollection(metadata, metadata
            .getBinaryCollection(Metadata.OBJECT_HAS_TYPES), Metadata.OBJECT_HAS_TYPES, metadata
            .getTypeObject(Metadata.TUPLE), metadata
            .getBinaryCollectionExtent(Metadata.OBJECT_HAS_TYPES));

      // typeHasAttributes
      Bootstrap.dressAsCollection(metadata, metadata
            .getBinaryCollection(Metadata.TYPE_HAS_ATTRIBUTES), Metadata.TYPE_HAS_ATTRIBUTES,
            metadata.getTypeObject(Metadata.TUPLE), metadata
                  .getBinaryCollectionExtent(Metadata.TYPE_HAS_ATTRIBUTES));

      // objectHasAttributeValues
      Bootstrap.dressAsCollection(metadata, metadata
            .getBinaryCollection(Metadata.OBJECT_HAS_ATTRIBUTEVALUES),
            Metadata.OBJECT_HAS_ATTRIBUTEVALUES, metadata.getTypeObject(Metadata.TUPLE), metadata
                  .getBinaryCollectionExtent(Metadata.OBJECT_HAS_ATTRIBUTEVALUES));

      // attributeValues
      Bootstrap.dressAsCollection(metadata,
            metadata.getBinaryCollection(Metadata.ATTRIBUTEVALUES), Metadata.ATTRIBUTEVALUES,
            metadata.getTypeObject(Metadata.TUPLE), metadata
                  .getBinaryCollectionExtent(Metadata.ATTRIBUTEVALUES));

      // typeHasExtent
      Bootstrap.dressAsCollection(metadata,
            metadata.getBinaryCollection(Metadata.TYPE_HAS_EXTENT), Metadata.TYPE_HAS_EXTENT,
            metadata.getTypeObject(Metadata.TUPLE), metadata
                  .getBinaryCollectionExtent(Metadata.TYPE_HAS_EXTENT));

      // typeISA
      Bootstrap.dressAsCollection(metadata, metadata.getBinaryCollection(Metadata.TYPE_ISA),
            Metadata.TYPE_ISA, metadata.getTypeObject(Metadata.TUPLE), metadata
                  .getBinaryCollectionExtent(Metadata.TYPE_ISA));

      // collectionISA
      Bootstrap.dressAsCollection(metadata, metadata.getBinaryCollection(Metadata.COLLECTION_ISA),
            Metadata.COLLECTION_ISA, metadata.getTypeObject(Metadata.TUPLE), metadata
                  .getBinaryCollectionExtent(Metadata.TYPE_ISA));
   }

   private static void dressAsBinaryCollection(final Metadata metadata,
         final ch.ethz.globis.javaom.core.Object binaryCollection,
         final ch.ethz.globis.javaom.core.Object domainType,
         final ch.ethz.globis.javaom.core.Object rangeType) {

      // TODO ... create tuple from name attribute to name value
      // final Tuple nameTuple =
      // metadata.createTuple(Metadata.ATTRIBUTEVALUES, metadata.getAttributeObject(
      // Metadata.BINARYCOLLECTION, Metadata.NAME), metadata.createStringValue(name));
      // ... create tuple from domain membertype attribute to domain membertype value
      final Tuple domainMembertypeTuple =
            metadata.createTuple(Metadata.ATTRIBUTEVALUES, metadata.getAttributeObject(
                  Metadata.BINARYCOLLECTION, Metadata.DOMAIN_MEMBERTYPE), domainType);
      // ... create tuple from range membertype attribute to range membertype value
      final Tuple rangeMembertypeTuple =
            metadata.createTuple(Metadata.ATTRIBUTEVALUES, metadata.getAttributeObject(
                  Metadata.BINARYCOLLECTION, Metadata.RANGE_MEMBERTYPE), rangeType);
      // TODO ... create tuple from extent attribute to extent value
      // final Tuple extentTuple =
      // metadata.createTuple(Metadata.ATTRIBUTEVALUES, metadata.getAttributeObject(
      // Metadata.BINARYCOLLECTION, Metadata.EXTENT), extent);

      // TODO ... add to association from name attribute to name value
      // metadata.getBinaryCollectionExtent(Metadata.ATTRIBUTEVALUES).add(nameTuple);
      // ... add to association from domain type attribute to domain type
      metadata.getBinaryCollectionExtent(Metadata.ATTRIBUTEVALUES).add(domainMembertypeTuple);
      // ... add to association from range type attribute to range type
      metadata.getBinaryCollectionExtent(Metadata.ATTRIBUTEVALUES).add(rangeMembertypeTuple);
      // TODO ... add to association from extent attribute to extent
      // metadata.getBinaryCollectionExtent(Metadata.ATTRIBUTEVALUES).add(extentTuple);

      // TODO ... add to association from binarycollection to its attribute values
      // metadata.getBinaryCollectionExtent(Metadata.OBJECT_HAS_ATTRIBUTEVALUES)
      // .add(
      // metadata.createTuple(Metadata.OBJECT_HAS_ATTRIBUTEVALUES, binaryCollection,
      // nameTuple));
      metadata.getBinaryCollectionExtent(Metadata.OBJECT_HAS_ATTRIBUTEVALUES).add(
            metadata.createTuple(Metadata.OBJECT_HAS_ATTRIBUTEVALUES, binaryCollection,
                  domainMembertypeTuple));
      metadata.getBinaryCollectionExtent(Metadata.OBJECT_HAS_ATTRIBUTEVALUES).add(
            metadata.createTuple(Metadata.OBJECT_HAS_ATTRIBUTEVALUES, binaryCollection,
                  rangeMembertypeTuple));
      // metadata.getBinaryCollectionExtent(Metadata.OBJECT_HAS_ATTRIBUTEVALUES).add(
      // metadata.createTuple(Metadata.OBJECT_HAS_ATTRIBUTEVALUES, binaryCollection,
      // extentTuple));
   }

   private static void dressAsBinaryCollections(final Metadata metadata) {

      // objectHasTypes
      Bootstrap.dressAsBinaryCollection(metadata, metadata
            .getBinaryCollection(Metadata.OBJECT_HAS_TYPES), metadata
            .getTypeObject(Metadata.OBJECT), metadata.getTypeObject(Metadata.TYPE));

      // typeHasAttributes
      Bootstrap.dressAsBinaryCollection(metadata, metadata
            .getBinaryCollection(Metadata.TYPE_HAS_ATTRIBUTES), metadata
            .getTypeObject(Metadata.TYPE), metadata.getTypeObject(Metadata.ATTRIBUTE));

      // objectHasAttributeValues
      Bootstrap.dressAsBinaryCollection(metadata, metadata
            .getBinaryCollection(Metadata.OBJECT_HAS_ATTRIBUTEVALUES), metadata
            .getTypeObject(Metadata.OBJECT), metadata.getTypeObject(Metadata.TUPLE));

      // attributeValues
      Bootstrap.dressAsBinaryCollection(metadata, metadata
            .getBinaryCollection(Metadata.ATTRIBUTEVALUES), metadata
            .getTypeObject(Metadata.ATTRIBUTE), metadata.getTypeObject(Metadata.OBJECT));

      // typeHasExtent
      Bootstrap.dressAsBinaryCollection(metadata, metadata
            .getBinaryCollection(Metadata.TYPE_HAS_EXTENT), metadata.getTypeObject(Metadata.TYPE),
            metadata.getTypeObject(Metadata.COLLECTION));

      // typeISA
      Bootstrap.dressAsBinaryCollection(metadata, metadata.getBinaryCollection(Metadata.TYPE_ISA),
            metadata.getTypeObject(Metadata.TYPE), metadata.getTypeObject(Metadata.TYPE));

      // collectionISA
      Bootstrap.dressAsBinaryCollection(metadata, metadata
            .getBinaryCollection(Metadata.COLLECTION_ISA), metadata
            .getTypeObject(Metadata.COLLECTION), metadata.getTypeObject(Metadata.COLLECTION));
   }

   private static void populateObjects(final Metadata metadata) {
      for (ch.ethz.globis.javaom.core.Object current : metadata.getObjects()) {
         metadata.getCollectionExtent(Metadata.OBJECT).add(current);
      }
   }

   private static void populateTypes(final Metadata metadata) {
      for (ch.ethz.globis.javaom.core.Object current : metadata.getTypeObjects()) {
         metadata.getCollectionExtent(Metadata.TYPE).add(current);
      }
   }

   private static void populateAttributes(final Metadata metadata) {
      for (ch.ethz.globis.javaom.core.Object current : metadata.getAttributeObjects()) {
         metadata.getCollectionExtent(Metadata.ATTRIBUTE).add(current);
      }
   }

   private static void populateCollections(final Metadata metadata) {
      for (ch.ethz.globis.javaom.core.Object current : metadata.getExtentCollections()) {
         metadata.getCollectionExtent(Metadata.COLLECTION).add(current);
      }
   }

   private static void populateBinaryCollections(final Metadata metadata) {
      for (ch.ethz.globis.javaom.core.Object current : metadata.getBinaryCollections()) {
         metadata.getCollectionExtent(Metadata.BINARYCOLLECTION).add(current);
      }
   }

   private static void populateStrings(final Metadata metadata) {
      for (ch.ethz.globis.javaom.core.Object current : metadata.getStringValues()) {
         metadata.getCollectionExtent(Metadata.STRING).add(current);
      }
   }

   private static void populateTuples(final Metadata metadata) {
      for (ch.ethz.globis.javaom.core.Object current : metadata.getTuples()) {
         metadata.getCollectionExtent(Metadata.TUPLE).add(current);
      }
   }

   private static void populateBulks(final Metadata metadata) {
      for (ch.ethz.globis.javaom.core.Object current : metadata.getExtents()) {
         metadata.getCollectionExtent(Metadata.BULK).add(current);
      }
   }

   private static void createTypeHierarchy(final Metadata metadata) {
      // ... everything is a subtype of object so their instances will be objects
      metadata.getBinaryCollectionExtent(Metadata.TYPE_ISA).add(
            metadata.createTuple(Metadata.TYPE_ISA, metadata.getTypeObject(Metadata.TYPE),
                  metadata.getTypeObject(Metadata.OBJECT)));
      metadata.getBinaryCollectionExtent(Metadata.TYPE_ISA).add(
            metadata.createTuple(Metadata.TYPE_ISA, metadata.getTypeObject(Metadata.COLLECTION),
                  metadata.getTypeObject(Metadata.OBJECT)));
      metadata.getBinaryCollectionExtent(Metadata.TYPE_ISA).add(
            metadata.createTuple(Metadata.TYPE_ISA, metadata
                  .getTypeObject(Metadata.BINARYCOLLECTION), metadata
                  .getTypeObject(Metadata.OBJECT)));
      metadata.getBinaryCollectionExtent(Metadata.TYPE_ISA).add(
            metadata.createTuple(Metadata.TYPE_ISA, metadata.getTypeObject(Metadata.ATTRIBUTE),
                  metadata.getTypeObject(Metadata.OBJECT)));
      metadata.getBinaryCollectionExtent(Metadata.TYPE_ISA).add(
            metadata.createTuple(Metadata.TYPE_ISA, metadata.getTypeObject(Metadata.TUPLE),
                  metadata.getTypeObject(Metadata.OBJECT)));
      metadata.getBinaryCollectionExtent(Metadata.TYPE_ISA).add(
            metadata.createTuple(Metadata.TYPE_ISA, metadata.getTypeObject(Metadata.STRING),
                  metadata.getTypeObject(Metadata.OBJECT)));
      metadata.getBinaryCollectionExtent(Metadata.TYPE_ISA).add(
            metadata.createTuple(Metadata.TYPE_ISA, metadata.getTypeObject(Metadata.BULK),
                  metadata.getTypeObject(Metadata.OBJECT)));
      // ... binary collection is a subtype of collection
      metadata.getBinaryCollectionExtent(Metadata.TYPE_ISA).add(
            metadata.createTuple(Metadata.TYPE_ISA, metadata
                  .getTypeObject(Metadata.BINARYCOLLECTION), metadata
                  .getTypeObject(Metadata.COLLECTION)));
   }

   private static void createCollectionHierarchy(final Metadata metadata) {
      // ... subcollections of objects
      metadata.getBinaryCollectionExtent(Metadata.COLLECTION_ISA).add(
            metadata.createTuple(Metadata.COLLECTION_ISA, metadata
                  .getExtentCollection(Metadata.TYPE), metadata
                  .getExtentCollection(Metadata.OBJECT)));
      metadata.getBinaryCollectionExtent(Metadata.COLLECTION_ISA).add(
            metadata.createTuple(Metadata.COLLECTION_ISA, metadata
                  .getExtentCollection(Metadata.ATTRIBUTE), metadata
                  .getExtentCollection(Metadata.OBJECT)));
      metadata.getBinaryCollectionExtent(Metadata.COLLECTION_ISA).add(
            metadata.createTuple(Metadata.COLLECTION_ISA, metadata
                  .getExtentCollection(Metadata.COLLECTION), metadata
                  .getExtentCollection(Metadata.OBJECT)));
      metadata.getBinaryCollectionExtent(Metadata.COLLECTION_ISA).add(
            metadata.createTuple(Metadata.COLLECTION_ISA, metadata
                  .getExtentCollection(Metadata.TUPLE), metadata
                  .getExtentCollection(Metadata.OBJECT)));
      metadata.getBinaryCollectionExtent(Metadata.COLLECTION_ISA).add(
            metadata.createTuple(Metadata.COLLECTION_ISA, metadata
                  .getExtentCollection(Metadata.STRING), metadata
                  .getExtentCollection(Metadata.OBJECT)));
      metadata.getBinaryCollectionExtent(Metadata.COLLECTION_ISA).add(
            metadata.createTuple(Metadata.COLLECTION_ISA, metadata
                  .getExtentCollection(Metadata.BULK), metadata
                  .getExtentCollection(Metadata.OBJECT)));
      // ... binary collections is subcollections collections
      metadata.getBinaryCollectionExtent(Metadata.COLLECTION_ISA).add(
            metadata.createTuple(Metadata.COLLECTION_ISA, metadata
                  .getExtentCollection(Metadata.BINARYCOLLECTION), metadata
                  .getExtentCollection(Metadata.COLLECTION)));
   }
}
